package com.haitao.wavebbs.tools;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;

/**
 * @author haitao
 * @data 2023/3/4
 */
public class SecurityTools {

    /**
     * 从安全性角度，key绝对不可以写在代码中，这里仅是为了方便。
     * 正式环境，key应存在安全的存储库中（例如HashiCorp Vault）
     * 生成key的网址：https://www.allkeysgenerator.com/
     */
    public static final String JWT_SECRET_KEY = "aPdSgVkYp3s6v9y$B?E(H+MbQeThWmZq4t7w!z%C*F)J@NcRfUjXn2r5u8x/A?D(";
    //token过期时间的毫秒值:5小时
    public static final long ttlMillis_defalut = 18000000;

    private static byte[] toBase64(String secret){
        return  Base64.getEncoder().encode(secret.getBytes());
    }

    /**
     * 系统的创建Jwt方法，例如你希望创建一个30分钟后过期的token，可这么用
     * createJwt(claimsMap,30*60*60*1000)
     * @param claimsMap 用户数据对象
     * @param ttlMillis 表示过期时间。单位为毫秒
     * @return
     */
    public static String createJwt(HashMap<String, Object> claimsMap,long ttlMillis){
        long time=System.currentTimeMillis() + ttlMillis;
        Date expiration = new Date(time);
        return Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .signWith(createSecretKey(), SignatureAlgorithm.HS256)
                .setClaims(claimsMap)
//                .setExpiration(expiration)
                .compact();

    }

    /**
     * 系统解析Jwt的方法。若解析成功，则返回claims对象，claims对象包含用户信息。
     * @param jwt
     * @return
     */
    public static Claims getClaimsFromJwt(String jwt){
        Jwt parse = Jwts.parserBuilder()
                .setSigningKey(createSecretKey())
                .build()
                .parseClaimsJws(jwt);
        Claims body = (Claims) parse.getBody();
        return body;
    }

    /**
     * 生成secretKey。该secretkey用于生成、解析JWT
     * @return
     */
    private static SecretKey createSecretKey(){
        return Keys.hmacShaKeyFor(SecurityTools.toBase64(SecurityTools.JWT_SECRET_KEY));
    }
}
